package com.lp.util;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.util.EntityUtils;

import javax.net.ssl.SSLContext;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Map;
import java.util.Set;

@Slf4j
public class ConnectUtil {

    /**
     * 注释: 以get方式调用第三方接口
     *
     * @param url 地址
     * @return java.lang.String
     * @author yangyongzhuo 2022/11/23 10:39
     */
    public static String connectGet(String url, Map<String, String> heads) {
        //创建HttpClient对象
        CloseableHttpClient httpClient = getCloseableHttpClient();


        HttpGet httpGet = new HttpGet(url);
        //token自定义header头，用于token验证使用
        addHeadersGet(heads, httpGet);

        httpGet.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36");
        try {
            HttpResponse response = httpClient.execute(httpGet);
            if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                //返回json格式
                return EntityUtils.toString(response.getEntity(), "UTF-8");
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (httpClient != null) {
                try {
                    httpClient.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

    public static String connectGet(String url) {
        return connectGet(url, null);
    }


    public static String connectPost(String url, JSONObject json, Map<String, String> heads) {
        //创建HttpClient对象
        CloseableHttpClient httpClient = HttpClientBuilder.create().build();
        HttpPost httpPost = new HttpPost(url);
        //token自定义header头，用于token验证使用
        addHeadersPost(heads, httpPost);

        httpPost.addHeader("Content-Type", "application/json");
        httpPost.addHeader("Accept", "application/json");
        httpPost.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36");
        try {
            StringEntity se = new StringEntity(json.toString(), StandardCharsets.UTF_8);
            se.setContentEncoding("UTF-8");
            //发送json数据需要设置contentType
            se.setContentType("application/json");
            //设置请求参数
            httpPost.setEntity(se);
            HttpResponse response = httpClient.execute(httpPost);
            if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                //返回json格式
                String res = EntityUtils.toString(response.getEntity(), "UTF-8");
                return res;
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (httpClient != null) {
                try {
                    httpClient.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

    public static String connectPost(String url, JSONObject json) {
        return connectPost(url, json, null);
    }


    public static String connectHttpsPost(String url, JSONObject json, Map<String, String> heads) {
        String body = "";
        CloseableHttpClient client = null;
        try {
            client = buildSSLCloseableHttpClient();

            //创建Get方式请求对象
            HttpPost httpPost = new HttpPost(url);
            addHeadersPost(heads, httpPost);
            //指定报文头Content-type、User-Agent
            httpPost.setHeader("Content-type", "application/x-www-form-urlencoded");
            httpPost.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; rv:6.0.2) Gecko/20100101 Firefox/6.0.2");

            StringEntity se = new StringEntity(json.toString(), StandardCharsets.UTF_8);
            se.setContentEncoding("UTF-8");
            //发送json数据需要设置contentType
            se.setContentType("application/json");
            //设置请求参数
            httpPost.setEntity(se);

            //执行请求操作，并拿到结果（同步阻塞）
            CloseableHttpResponse response = client.execute(httpPost);

            //获取结果实体
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                //按指定编码转换结果实体为String类型
                body = EntityUtils.toString(entity, "UTF-8");
            }

            EntityUtils.consume(entity);
            //释放链接
            response.close();
        } catch (Exception e) {
            e.printStackTrace();
            System.err.println(e);
        } finally {
            if (client != null) {
                try {
                    client.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }
        return body;
    }

    public static String connectHttpsPost(String url, Map<String, String> heads) {
        return connectHttpsPost(url, new JSONObject(), heads);
    }

    public static String connectHttpsPost(String url, JSONObject json) {
        return connectHttpsPost(url, json, null);
    }

    public static String connectHttpsPost(String url) {
        return connectHttpsPost(url, new JSONObject(), null);
    }


    public static String connectHttpsGet(String url, Map<String, String> heads) {
        String body = "";
        CloseableHttpClient client = null;
        try {
            client = buildSSLCloseableHttpClient();

            //创建Get方式请求对象
            HttpGet httpGet = new HttpGet(url);
            addHeadersGet(heads, httpGet);
            //指定报文头Content-type、User-Agent
            httpGet.setHeader("Content-type", "application/x-www-form-urlencoded");

            httpGet.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; rv:6.0.2) Gecko/20100101 Firefox/6.0.2");


            //执行请求操作，并拿到结果（同步阻塞）
            CloseableHttpResponse response = client.execute(httpGet);

            //获取结果实体
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                //按指定编码转换结果实体为String类型
                body = EntityUtils.toString(entity, "UTF-8");
            }

            EntityUtils.consume(entity);
            //释放链接
            response.close();
            System.out.println("body:" + body);
        } catch (Exception e) {
            e.printStackTrace();
            System.err.println(e);
        } finally {
            if (client != null) {
                try {
                    client.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }
        return body;
    }

    public static String connectHttpsGet(String url) {
        return connectHttpsGet(url, null);
    }


    private static void addHeadersPost(Map<String, String> heads, HttpPost httpPost) {
        if (heads != null && heads.size() != 0) {
            Set<String> keys = heads.keySet();
            for (String key : keys) {
                httpPost.addHeader(key, heads.get(key));
            }
        }
    }

    private static void addHeadersGet(Map<String, String> heads, HttpGet httpGet) {
        if (heads != null && heads.size() != 0) {
            Set<String> keys = heads.keySet();
            for (String key : keys) {
                httpGet.addHeader(key, heads.get(key));
            }
        }
    }

    private static CloseableHttpClient buildSSLCloseableHttpClient() throws Exception {
        SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
            // 信任所有
            @Override
            public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                return true;
            }
        }).build();
        // ALLOW_ALL_HOSTNAME_VERIFIER:这个主机名验证器基本上是关闭主机名验证的,实现的是一个空操作，并且不会抛出javax.net.ssl.SSLException异常。
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, new String[]{"TLSv1", "TLSv1.2", "TLSv1.1"}, null,
                SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
        return HttpClients.custom().setSSLSocketFactory(sslsf).build();
    }

    private static CloseableHttpClient getCloseableHttpClient() {
        CloseableHttpClient httpClient = HttpClients.createDefault();

// 设置超时时间（单位是毫秒）
        int connectTimeout = 1000; // 连接超时时间
        int connectionRequestTimeout = 500; // 获取连接的超时时间
        int socketTimeout = 2000; // 数据读取超时时间

// 构建RequestConfig
        RequestConfig config = RequestConfig.custom()
                .setConnectTimeout(connectTimeout)
                .setConnectionRequestTimeout(connectionRequestTimeout)
                .setSocketTimeout(socketTimeout)
                .build();

// 设置默认的RequestConfig
        httpClient = HttpClients.custom()
                .setDefaultRequestConfig(config)
                .build();
        return httpClient;
    }

    public static String connectionGet(String url) {
        StringBuilder response = new StringBuilder();
        try {
            URL urlConnection = new URL(url);
            HttpURLConnection conn = (HttpURLConnection) urlConnection.openConnection();
            conn.setConnectTimeout(5000); // 连接超时设置为5秒
            conn.setReadTimeout(5000);    // 读取超时设置为5秒
            conn.setRequestMethod("GET");

            int responseCode = conn.getResponseCode();

            if (responseCode == HttpURLConnection.HTTP_OK) {
                BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
                String inputLine;

                while ((inputLine = in.readLine()) != null) {
                    response.append(inputLine);
                }
                in.close();

                return response.toString();
            } else {
                log.error("网络请求异常");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return response.toString();
    }
}
